<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件传输 - 优化版</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
        }

        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
            color: #ffffff;
            line-height: 1.6;
            padding: 15px;
            min-height: 100vh;
        }

        .container {
            max-width: 800px;
            margin: 20px auto;
            background: rgba(25, 25, 35, 0.85);
            border-radius: 18px;
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
            padding: 25px;
            backdrop-filter: blur(10px);
            border: 1px solid rgba(255, 255, 255, 0.1);
        }

        header {
            text-align: center;
            margin-bottom: 25px;
            padding-bottom: 15px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }

        h1 {
            font-size: 28px;
            font-weight: 700;
            background: linear-gradient(90deg, #4facfe, #00f2fe);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            margin-bottom: 8px;
        }

        .subtitle {
            color: #a0a0c0;
            font-size: 15px;
            margin-top: 8px;
        }

        .card {
            background: rgba(40, 40, 60, 0.6);
            border-radius: 14px;
            padding: 20px;
            margin-bottom: 25px;
            box-shadow: 0 6px 18px rgba(0, 0, 0, 0.2);
        }

        .card-title {
            font-size: 18px;
            font-weight: 600;
            margin-bottom: 15px;
            color: #4facfe;
            display: flex;
            align-items: center;
        }

        .card-title i {
            margin-right: 8px;
            font-size: 22px;
        }

        .progress-container {
            margin: 15px 0;
            display: none;
        }

        .progress-header {
            display: flex;
            justify-content: space-between;
            margin-bottom: 6px;
            font-size: 13px;
            color: #a0a0c0;
        }

        .progress-bar {
            height: 10px;
            background: rgba(100, 100, 130, 0.4);
            border-radius: 8px;
            overflow: hidden;
        }

        .progress-fill {
            height: 100%;
            background: linear-gradient(90deg, #4facfe, #00f2fe);
            width: 0%;
            transition: width 0.3s ease;
        }

        .stats {
            display: flex;
            justify-content: space-between;
            margin-top: 8px;
            font-size: 12px;
            color: #a0a0c0;
        }

        .file-input {
            display: none;
        }

        .file-input-container {
            position: relative;
            margin-bottom: 15px;
        }

        .file-input-label {
            display: block;
            width: 100%;
            padding: 12px;
            background: rgba(80, 100, 220, 0.2);
            color: #4facfe;
            border-radius: 10px;
            font-size: 15px;
            font-weight: 500;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s;
            border: 2px dashed rgba(79, 172, 254, 0.4);
        }

        .file-input-label:hover {
            background: rgba(80, 100, 220, 0.3);
            border-color: #4facfe;
        }

        .btn-group {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 12px;
            margin-top: 15px;
        }

        .btn {
            padding: 12px;
            border-radius: 10px;
            font-size: 15px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s;
            border: none;
            text-align: center;
        }

        .btn-upload {
            background: linear-gradient(90deg, #4facfe, #00f2fe);
            color: white;
        }

        .btn-upload:hover {
            opacity: 0.9;
            transform: translateY(-2px);
        }

        .btn-upload:disabled {
            background: #555;
            cursor: not-allowed;
            transform: none;
        }

        .btn-download {
            background: linear-gradient(90deg, #0ba360, #3cba92);
            color: white;
        }

        .btn-download:hover {
            opacity: 0.9;
            transform: translateY(-2px);
        }

        .segment-control {
            display: flex;
            background: rgba(50, 50, 70, 0.6);
            border-radius: 8px;
            overflow: hidden;
            margin: 15px 0;
        }

        .segment {
            flex: 1;
            padding: 10px;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s;
            color: #a0a0c0;
            font-size: 14px;
        }

        .segment.active {
            background: rgba(80, 100, 220, 0.4);
            color: white;
            font-weight: 600;
        }

        .file-list {
            max-height: 180px;
            overflow-y: auto;
            margin: 15px 0;
            background: rgba(30, 30, 45, 0.6);
            border-radius: 10px;
            padding: 12px;
        }

        .file-item {
            display: flex;
            justify-content: space-between;
            padding: 8px 10px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.05);
            transition: all 0.2s;
            border-radius: 6px;
        }

        .file-item:hover {
            background: rgba(255, 255, 255, 0.05);
        }

        .file-item.selected {
            background: rgba(79, 172, 254, 0.25);
        }

        .file-item:last-child {
            border-bottom: none;
        }

        .file-name {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            max-width: 70%;
            font-size: 14px;
        }

        .file-size {
            color: #a0a0c0;
            font-size: 12px;
            white-space: nowrap;
            margin-left: 10px;
        }

        .file-info-row {
            display: flex;
            justify-content: space-between;
            margin-bottom: 5px;
        }

        .tech-info {
            margin-top: 25px;
            padding-top: 15px;
            border-top: 1px solid rgba(255, 255, 255, 0.1);
            font-size: 13px;
            color: #a0a0c0;
            text-align: center;
        }

        .optimized {
            display: inline-block;
            background: rgba(11, 163, 96, 0.2);
            color: #3cba92;
            padding: 4px 8px;
            border-radius: 20px;
            margin-top: 8px;
            font-weight: 600;
            font-size: 12px;
        }

        .selected-count {
            font-size: 13px;
            color: #4facfe;
            margin-top: 8px;
            text-align: right;
        }

        @media (max-width: 600px) {
            .container {
                padding: 15px;
            }

            .btn-group {
                grid-template-columns: 1fr;
            }

            h1 {
                font-size: 24px;
            }

            .file-name {
                max-width: 60%;
            }
        }

        .btn-hidden {
            display: none;
        }
    </style>
</head>

<body>
    <div class="container">
        <header>
            <h1>高速文件传输系统</h1>
            <p class="subtitle">支持大文件分片下载与断点续传</p>
        </header>

        <div class="card">
            <h2 class="card-title">
                <i>📤</i> 上传文件
            </h2>
            <div class="progress-container" id="uploadProgressContainer">
                <div class="progress-header">
                    <span>上传进度</span>
                    <span id="uploadPercent">0%</span>
                </div>
                <div class="progress-bar">
                    <div class="progress-fill" id="uploadProgress"></div>
                </div>
                <div class="stats">
                    <span id="uploadSpeed">速度: 0 MB/s</span>
                    <span id="uploadTime">剩余时间: --</span>
                </div>
            </div>
            <div class="file-input-container">
                <label for="fileInput" id="fileInputLabel" class="file-input-label">选择文件或拖放至此</label>
                <input type="file" id="fileInput" class="file-input" multiple>
            </div>
            <div id="fileInfo"></div>
            <div class="btn-group">
                <button id="uploadButton" class="btn btn-upload">开始上传</button>
                <button id="cancelUpload" class="btn btn-hidden" style="background: #555; color: #fff">取消上传</button>
            </div>
        </div>

        <div class="card">
            <h2 class="card-title">
                <i>📥</i> 下载文件
            </h2>
            <p style="margin-bottom: 12px; color: #a0a0c0;">选择下载源：</p>
            <div class="segment-control">
                <div class="segment active" data-source="downloads">下载目录</div>
                <div class="segment" data-source="uploads">上传目录</div>
            </div>

            <div class="file-info-row">
                <span>可用文件列表</span>
                <span id="selectedCount" class="selected-count">已选: 0</span>
            </div>

            <div class="file-list" id="fileList">
                <div class="file-item">
                    <div class="file-name">加载中...</div>
                    <div class="file-size">--</div>
                </div>
            </div>

            <div class="progress-container" id="downloadProgressContainer">
                <div class="progress-header">
                    <span>下载进度</span>
                    <span id="downloadPercent">0%</span>
                </div>
                <div class="progress-bar">
                    <div class="progress-fill" id="downloadProgress"></div>
                </div>
                <div class="stats">
                    <span id="downloadSpeed">速度: 0 MB/s</span>
                    <span id="downloadTime">剩余时间: --</span>
                    <span id="chunkInfo">分片: 0/0</span>
                </div>
            </div>

            <div class="btn-group">
                <button id="downloadButton" class="btn btn-download">下载所选文件</button>
                <button id="cancelDownload" class="btn btn-hidden" style="background: #555; color: #fff">取消下载</button>
            </div>
        </div>

        <div class="tech-info">
            <p>使用分片下载技术优化大文件传输</p>
            <div class="optimized">并行下载 · 内存优化 · 断点续传</div>
        </div>
    </div>

    <script>
        // 初始化变量
        let uploadXHR = null;
        let downloadManager = null;
        let selectedFiles = [];
        let downloadSource = 'downloads';
        let selectedFileItems = [];

        // DOM元素
        const fileInput = document.getElementById('fileInput');
        const uploadButton = document.getElementById('uploadButton');
        const cancelUpload = document.getElementById('cancelUpload');
        const downloadButton = document.getElementById('downloadButton');
        const cancelDownload = document.getElementById('cancelDownload');
        const fileList = document.getElementById('fileList');
        const segments = document.querySelectorAll('.segment');
        const selectedCount = document.getElementById('selectedCount');

        // 更新按钮状态函数
        function toggleButtons(operation, showCancel) {
            if (operation === 'upload') {
                if (showCancel) {
                    document.getElementById('uploadButton').classList.add('btn-hidden');
                    document.getElementById('fileInputLabel').classList.add('btn-hidden');
                    document.getElementById('cancelUpload').classList.remove('btn-hidden');
                } else {
                    document.getElementById('uploadButton').classList.remove('btn-hidden');
                    document.getElementById('fileInputLabel').classList.remove('btn-hidden');
                    document.getElementById('cancelUpload').classList.add('btn-hidden');
                }
            } else if (operation === 'download') {
                if (showCancel) {
                    document.getElementById('downloadButton').classList.add('btn-hidden');
                    document.getElementById('cancelDownload').classList.remove('btn-hidden');
                } else {
                    document.getElementById('downloadButton').classList.remove('btn-hidden');
                    document.getElementById('cancelDownload').classList.add('btn-hidden');
                }
            }
        }

        // 初始化事件监听器
        document.addEventListener('DOMContentLoaded', function () {
            // 初始化文件选择
            fileInput.addEventListener('change', handleFileSelect);

            // 初始化上传按钮
            uploadButton.addEventListener('click', startUpload);
            cancelUpload.addEventListener('click', cancelUploadProcess);

            // 初始化下载按钮
            downloadButton.addEventListener('click', startDownload);
            cancelDownload.addEventListener('click', cancelDownloadProcess);

            // 初始化下载源切换
            segments.forEach(segment => {
                segment.addEventListener('click', function () {
                    segments.forEach(s => s.classList.remove('active'));
                    this.classList.add('active');
                    downloadSource = this.dataset.source;
                    selectedFileItems = [];
                    updateSelectedCount();
                    loadFileList();
                });
            });

            // 加载文件列表
            loadFileList();

            // 初始化拖放功能
            initDragAndDrop();
        });

        // 更新选中计数
        function updateSelectedCount() {
            selectedCount.textContent = `已选: ${selectedFileItems.length}`;
        }

        // 处理文件选择
        function handleFileSelect(e) {
            const files = e.target.files;
            selectedFiles = Array.from(files);

            if (files.length > 0) {
                let fileInfo = `已选择 ${files.length} 个文件: `;
                for (let i = 0; i < Math.min(files.length, 3); i++) {
                    fileInfo += `<br>${files[i].name} (${formatSize(files[i].size)})`;
                }
                if (files.length > 3) fileInfo += `<br>...及其他 ${files.length - 3} 个文件`;

                document.getElementById('fileInfo').innerHTML = fileInfo;
            }
        }

        // 初始化拖放功能
        function initDragAndDrop() {
            const dropArea = document.querySelector('.file-input-label');

            ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
                dropArea.addEventListener(eventName, preventDefaults, false);
            });

            function preventDefaults(e) {
                e.preventDefault();
                e.stopPropagation();
            }

            ['dragenter', 'dragover'].forEach(eventName => {
                dropArea.addEventListener(eventName, highlight, false);
            });

            ['dragleave', 'drop'].forEach(eventName => {
                dropArea.addEventListener(eventName, unhighlight, false);
            });

            function highlight() {
                dropArea.style.borderColor = '#4facfe';
                dropArea.style.backgroundColor = 'rgba(79, 172, 254, 0.1)';
            }

            function unhighlight() {
                dropArea.style.borderColor = 'rgba(79, 172, 254, 0.4)';
                dropArea.style.backgroundColor = 'rgba(80, 100, 220, 0.2)';
            }

            dropArea.addEventListener('drop', handleDrop, false);

            function handleDrop(e) {
                const dt = e.dataTransfer;
                const files = dt.files;
                fileInput.files = files;
                handleFileSelect({ target: fileInput });
            }
        }

        // 开始上传
        function startUpload() {
            if (selectedFiles.length === 0) {
                alert('请选择要上传的文件');
                return;
            }

            // 更新按钮状态
            toggleButtons('upload', true);

            const formData = new FormData();
            selectedFiles.forEach(file => {
                formData.append('file', file);
            });

            // 显示进度条
            document.getElementById('uploadProgressContainer').style.display = 'block';

            uploadXHR = new XMLHttpRequest();
            uploadXHR.open('POST', `http://${window.location.hostname}:3000/upload`, true);

            // 更新进度
            uploadXHR.upload.addEventListener('progress', function (e) {
                if (e.lengthComputable) {
                    const percent = Math.round((e.loaded / e.total) * 100);
                    document.getElementById('uploadProgress').style.width = `${percent}%`;
                    document.getElementById('uploadPercent').textContent = `${percent}%`;

                    // 计算速度
                    const currentTime = new Date().getTime();
                    const elapsedTime = (currentTime - startTime) / 1000; // 秒
                    const loadedMB = (e.loaded / (1024 * 1024)).toFixed(2);
                    const speedMBps = (loadedMB / elapsedTime).toFixed(2);

                    document.getElementById('uploadSpeed').textContent = `速度: ${speedMBps} MB/s`;

                    // 计算剩余时间
                    const remainingBytes = e.total - e.loaded;
                    const remainingSeconds = (remainingBytes / (speedMBps * 1024 * 1024)).toFixed(0);

                    if (remainingSeconds > 0) {
                        document.getElementById('uploadTime').textContent = `剩余时间: ${formatTime(remainingSeconds)}`;
                    }
                }
            });

            // 上传完成
            uploadXHR.onload = function () {
                if (uploadXHR.status === 200) {
                    document.getElementById('fileInfo').innerHTML =
                        `<span style="color: #3cba92;">上传成功!</span> ${selectedFiles.length} 个文件已上传`;
                    selectedFiles = [];
                    fileInput.value = '';
                    loadFileList();
                } else {
                    document.getElementById('fileInfo').innerHTML =
                        `<span style="color: #ff6b6b;">上传失败: ${uploadXHR.statusText}</span>`;
                }

                // 重置进度条
                setTimeout(() => {
                    document.getElementById('uploadProgressContainer').style.display = 'none';
                    document.getElementById('uploadProgress').style.width = '0%';
                }, 2000);
                // 恢复按钮状态
                toggleButtons('upload', false);
            };

            // 错误处理
            uploadXHR.onerror = function () {
                document.getElementById('fileInfo').innerHTML =
                    `<span style="color: #ff6b6b;">上传失败: 网络错误</span>`;
            };

            const startTime = new Date().getTime();
            uploadXHR.send(formData);
        }

        // 取消上传
        function cancelUploadProcess() {
            if (uploadXHR) {
                uploadXHR.abort();
                document.getElementById('fileInfo').innerHTML =
                    `<span style="color: #ff9f43;">上传已取消</span>`;
                document.getElementById('uploadProgressContainer').style.display = 'none';
                document.getElementById('uploadProgress').style.width = '0%';
            }
            // 恢复按钮状态
            toggleButtons('upload', false);
        }

        // 加载文件列表
        async function loadFileList() {
            fileList.innerHTML = '<div class="file-item"><div class="file-name">加载中...</div><div class="file-size">--</div></div>';

            try {
                const response = await fetch(`http://${window.location.hostname}:3000/get-file-list?source=${downloadSource}`);
                const files = await response.json();

                if (files.length === 0) {
                    fileList.innerHTML = '<div class="file-item"><div class="file-name">没有找到文件</div><div class="file-size">--</div></div>';
                    return;
                }

                fileList.innerHTML = '';
                files.forEach(file => {
                    const fileItem = document.createElement('div');
                    fileItem.className = 'file-item';
                    fileItem.innerHTML = `
                        <div class="file-name">${file.name}</div>
                        <div class="file-size">${formatSize(file.size)}</div>
                    `;

                    // 存储文件元数据
                    fileItem.dataset.name = file.name;
                    fileItem.dataset.category = file.category;
                    fileItem.dataset.size = file.size;

                    fileItem.addEventListener('click', function () {
                        const isSelected = this.classList.contains('selected');

                        if (isSelected) {
                            this.classList.remove('selected');
                            // 从选中列表中移除
                            selectedFileItems = selectedFileItems.filter(item =>
                                item.name !== file.name || item.category !== file.category);
                        } else {
                            this.classList.add('selected');
                            // 添加到选中列表
                            selectedFileItems.push({
                                name: file.name,
                                category: file.category,
                                size: file.size
                            });
                        }

                        updateSelectedCount();
                    });

                    fileList.appendChild(fileItem);
                });
            } catch (error) {
                fileList.innerHTML = '<div class="file-item"><div class="file-name">加载失败</div><div class="file-size">--</div></div>';
                console.error('加载文件列表失败:', error);
            }
        }

        // 开始下载
        async function startDownload() {
            if (selectedFileItems.length === 0) {
                alert('请选择要下载的文件');
                return;
            }

            // 更新按钮状态
            toggleButtons('download', true);

            // 隐藏进度条（华为式下载不显示进度）
            document.getElementById('downloadProgressContainer').style.display = 'none';

            // 显示下载提示
            document.getElementById('chunkInfo').textContent = '正在准备下载...';

            // 为每个文件创建直接下载
            for (const file of selectedFileItems) {
                try {
                    // 1. 创建隐藏的<a>标签
                    const a = document.createElement('a');
                    a.style.display = 'none';

                    // 2. 设置下载URL（使用完整文件下载接口）
                    a.href = `http://${window.location.hostname}:3000/download-full?name=${encodeURIComponent(file.name)}&category=${encodeURIComponent(file.category)}&source=${downloadSource}`;

                    // 3. 设置download属性触发浏览器下载行为
                    a.download = file.name;

                    // 4. 添加到DOM并触发点击
                    document.body.appendChild(a);
                    a.click();

                    // 5. 清理
                    setTimeout(() => {
                        document.body.removeChild(a);
                    }, 100);

                    // 6. 显示下载反馈
                    showDownloadToast(`开始下载: ${file.name}`);

                } catch (error) {
                    console.error('下载失败:', error);
                    showDownloadToast(`下载失败: ${file.name}`, true);
                }
            }
            // 恢复按钮状态
            setTimeout(() => toggleButtons('download', false), 1000);
        }

        // 显示下载提示
        function showDownloadToast(message, isError = false) {
            const toast = document.createElement('div');
            toast.textContent = message;
            toast.style.cssText = `
        position: fixed;
        bottom: 20px;
        right: 20px;
        padding: 10px 15px;
        border-radius: 8px;
        background: ${isError ? '#ff6b6b' : '#3cba92'};
        color: white;
        font-size: 14px;
        z-index: 1000;
        box-shadow: 0 4px 12px rgba(0,0,0,0.15);
        animation: fadeInOut 3s ease-in-out;
    `;

            document.body.appendChild(toast);

            // 自动移除
            setTimeout(() => {
                if (toast.parentNode) {
                    document.body.removeChild(toast);
                }
            }, 3000);
        }

        // 添加CSS动画
        const style = document.createElement('style');
        style.textContent = `
            @keyframes fadeInOut {
                0% { opacity: 0; transform: translateY(20px); }
                10% { opacity: 1; transform: translateY(0); }
                90% { opacity: 1; transform: translateY(0); }
                100% { opacity: 0; transform: translateY(20px); }
            }
        `;
        document.head.appendChild(style);

        // 取消下载
        function cancelDownloadProcess() {
            if (downloadManager) {
                // 中止所有活动的请求
                downloadManager.activeRequests = [];
                downloadManager = null;

                document.getElementById('downloadProgressContainer').style.display = 'none';
                document.getElementById('chunkInfo').textContent = '下载已取消';
            }
            // 恢复按钮状态
            toggleButtons('download', false);
        }

        // 工具函数：格式化时间
        function formatTime(seconds) {
            const hours = Math.floor(seconds / 3600);
            const minutes = Math.floor((seconds % 3600) / 60);
            const secs = Math.floor(seconds % 60);

            if (hours > 0) {
                return `${hours}h ${minutes}m ${secs}s`;
            } else if (minutes > 0) {
                return `${minutes}m ${secs}s`;
            } else {
                return `${secs}s`;
            }
        }

        // 工具函数：格式化文件大小
        function formatSize(bytes) {
            if (bytes >= 1073741824) {
                return (bytes / 1073741824).toFixed(2) + ' GB';
            } else if (bytes >= 1048576) {
                return (bytes / 1048576).toFixed(2) + ' MB';
            } else if (bytes >= 1024) {
                return (bytes / 1024).toFixed(2) + ' KB';
            } else {
                return bytes + ' B';
            }
        }
    </script>
</body>

</html>